package com.hwn.datax.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import com.hwn.datax.domain.RepositoryConfig;
import com.hwn.datax.domain.RepositorySource;
import com.hwn.datax.domain.TreeItemNode;
import com.hwn.datax.service.RepositoryConfigService;
import com.hwn.datax.service.RepositorySourceService;
import com.hwn.datax.utils.AlertUtil;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.stage.Stage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import java.util.List;

/**
 * @author wnhuang
 * @date 2024/6/1 15:42
 */
@Controller
public class ConnectionFormController {

    @FXML
    public TextField name;
    @FXML
    public TextField host;
    @FXML
    public TextField port;
    @FXML
    public TextField repositoryName;
    @FXML
    public TextField url;
    @FXML
    public TextField username;
    @FXML
    public PasswordField password;
    @FXML
    public ComboBox<TreeItemNode<RepositoryConfig>> dbType;
    @FXML
    public Button cancelButton;

    @FXML
    public TextField driverClassTextField;
    public ListView<TreeItemNode<RepositorySource>> connectionListView;
    public Button removeBtn;

    private RepositorySource repositorySource = new RepositorySource();

    @Autowired
    RepositorySourceService repositorySourceService;

    @Autowired
    private RepositoryConfigService repoConfigService;

    private RepositoryConfig repositoryConfig;

    @FXML
    public void initialize() {
        loadConnectionList();
        List<RepositoryConfig> list = repoConfigService.list();
        dbType.getItems().addAll(list.stream().map(t -> new TreeItemNode<>(t.getDbName(), t)).toList());

        dbType.setOnAction(event -> {
            if (dbType.getValue() != null && dbType.getValue().getValue() != null) {
                TreeItemNode<RepositoryConfig> treeItemNode = dbType.getValue();
                RepositoryConfig repositoryConfig = treeItemNode.getValue();
                this.repositoryConfig = repositoryConfig;
                bindModel(repositoryConfig);
            } else {
                this.repositoryConfig = null;
            }
        });

        removeBtn.setOnAction(event -> {
            repositorySourceService.remove(repositorySource.getId());
            loadConnectionList();
        });

        host.textProperty().addListener((observableValue, oldValue, newValue) -> {
            updateJdbcUrl();
        });
        port.textProperty().addListener((observableValue, oldValue, newValue) -> {
            updateJdbcUrl();
        });
        repositoryName.textProperty().addListener((observableValue, oldValue, newValue) -> {
            updateJdbcUrl();
        });
    }

    private void loadConnectionList() {
        connectionListView.getItems().clear();
        connectionListView.getItems().addAll(repositorySourceService.list().stream().map(t -> new TreeItemNode<>(t.getName(), t)).toList());
        connectionListView.getSelectionModel().selectedItemProperty().addListener((observableValue, oldValue, newValue) -> {
            if (newValue == null) {
                repositorySource = new RepositorySource();
                removeBtn.setDisable(true);
            } else {
                removeBtn.setDisable(false);
                BeanUtil.copyProperties(newValue.getValue(), repositorySource);
            }
            updateUiFromModel();
        });
    }

    private void updateJdbcUrl() {
        if (this.repositoryConfig == null) {
            return;
        }
        String hostStr = host.getText();
        String portStr = port.getText();
        String repositoryNameStr = repositoryName.getText();

        String jdbcUrl = this.repositoryConfig.getUrlTemplate();

        if (hostStr != null && !hostStr.isBlank()) {
            jdbcUrl = jdbcUrl.replace("${host}", hostStr);
        }

        if (portStr != null && !portStr.isBlank()) {
            jdbcUrl = jdbcUrl.replace("${port}", portStr);
        }

        if (repositoryNameStr == null || repositoryNameStr.isBlank()) {
            repositoryNameStr = "";
        }
        jdbcUrl = jdbcUrl.replace("${repositoryName}", repositoryNameStr);
        // 更新JDBC URL显示
        url.setText(jdbcUrl);
    }

    private void bindModel(RepositoryConfig repositoryConfig) {
        url.setPromptText(repositoryConfig.getUrlTemplate());
        driverClassTextField.setText(repositoryConfig.getDriverClass());
        port.setText(String.valueOf(repositoryConfig.getDefaultPort()));
    }

    @FXML
    public void handleTestConnection(ActionEvent actionEvent) {
        updateModeFromUi();
        repositorySourceService.testConnection(repositorySource);
        AlertUtil.showSuccessAlert("有效的连接");
    }

    private void updateModeFromUi() {
        repositorySource.setHost(host.getText());
        repositorySource.setPort(Integer.parseInt(port.getText()));
        repositorySource.setName(name.getText());
        repositorySource.setUsername(username.getText());
        repositorySource.setPassword(password.getText());
        repositorySource.setUrl(url.getText());
        TreeItemNode<RepositoryConfig> treeItemNode = dbType.getValue();
        RepositoryConfig repositoryConfig = treeItemNode.getValue();
        repositorySource.setDbTypeName(repositoryConfig.getDbName());
        repositorySource.setDriverClassName(driverClassTextField.getText());
    }

    private void updateUiFromModel() {
        host.setText(repositorySource.getHost());
        port.setText(Convert.toStr(repositorySource.getPort(), ""));
        name.setText(repositorySource.getName());
        username.setText(repositorySource.getUsername());
        password.setText(repositorySource.getPassword());
        url.setText(repositorySource.getUrl());

        // Assuming dbType is a ComboBox that holds TreeItemNode<RepositoryConfig> items
        // and you want to select the one that matches your repositorySource's dbTypeName
        boolean foundMatch = false;
        for (TreeItemNode<RepositoryConfig> item : dbType.getItems()) {
            RepositoryConfig config = item.getValue();
            if (config.getDbName().equals(repositorySource.getDbTypeName())) {
                dbType.getSelectionModel().select(item);
                foundMatch = true;
                break;
            }
        }
        if (!foundMatch) {
            dbType.getSelectionModel().select(null);
        }
        driverClassTextField.setText(repositorySource.getDriverClassName());
    }

    @FXML
    public void handleCancel(ActionEvent actionEvent) {
        // Get the stage and close it
        Stage stage = (Stage) cancelButton.getScene().getWindow();
        stage.close();
    }

    public void handleSave(ActionEvent actionEvent) {
        updateModeFromUi();
        repositorySourceService.save(repositorySource);
        AlertUtil.showSuccessAlert("保存成功！");
        loadConnectionList();
        connectionListView.refresh();
    }

    public void handleAdd(ActionEvent actionEvent) {
        this.repositoryConfig = null;
        BeanUtil.copyProperties(new RepositorySource(), repositorySource);
        updateUiFromModel();
    }
}
